﻿using System;
using System.Data;
using System.Linq;
using DbMetadata.Providers;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DbMetadata.Tests
{
    [TestClass]
    public abstract class DbMetadataTests
    {
        private const int TableCount = 29;
        private const int PrimaryKeyCount = 16;
        private const int ColumnCount = 190;
        private const int ForeignKeyCount = 13;

        [TestMethod]
        public void MustReadTables()
        {
            using(var connection = CreateConnection())
            {
                var metadataExtractor = CreateMetadataExtractor(connection);
                var tables = metadataExtractor.ReadTables();
                Assert.AreEqual(TableCount,tables.Count());
            }
        }

        [TestMethod]
        public void MustReadColumns()
        {
            using (var connection = CreateConnection())
            {
                var metadataExtractor = CreateMetadataExtractor(connection);
                var columns = metadataExtractor.ReadColumns();
                Assert.AreEqual(ColumnCount, columns.Count());
            }
        }


        [TestMethod]
        public void MustReadForeignKeys()
        {
            using (var connection = CreateConnection())
            {
                var metadataExtractor = CreateMetadataExtractor(connection);
                var foreignKeys = metadataExtractor.ReadForeignKeys();
                Assert.AreEqual(ForeignKeyCount, foreignKeys.Count());
            }
        }

        [TestMethod]
        public void MustReadPrimaryKeys()
        {
            using (var connection = CreateConnection())
            {
                var metadataExtractor = CreateMetadataExtractor(connection);
                var primaryKeys = metadataExtractor.ReadPrimaryKeys();
                Assert.AreEqual(PrimaryKeyCount, primaryKeys.Count());
            }
        }
        
        [TestMethod]
        public void MustBeAbleToGetTables()
        {
            using (var connection = CreateConnection())
            {
                var tables = connection.GetMetadata().Tables;                        
                Assert.IsNotNull(tables);
                Assert.AreEqual(TableCount,tables.Count());
            }

            using (var connection = CreateConnection())
            {
                var tables = connection.GetMetadata().Tables;
                foreach (var table in tables)
                {
                    Console.WriteLine(table.TableName);
                }
            }
        }

        [TestMethod]
        public void MustBeAbleToGetPrimaryKeys()
        {
            using (var connection = CreateConnection())
            {                
                var tables = connection.GetMetadata().Tables;
                foreach (var dbTableInfo in tables.Where(t => t.TableType == DbTableType.Table))
                {
                    Assert.IsNotNull(dbTableInfo.PrimaryKey);
                }
            }
        }


        [TestMethod]
        public void MusBeAbleToGetForeignKeys()
        {
            using (var connection = CreateConnection())
            {                
                var ordersTable = connection.GetMetadata().Tables.Where(t => t.TableName == "Orders").FirstOrDefault();
                Assert.AreEqual(3,ordersTable.ForeignKeys.Count);                
            }
        }


        [TestMethod]
        public void MustBeAbleToReadCustomProviderFactoryFromConfiguration()
        {            
            var factory = DbMetadataProviderFactories.GetFactories().Where(f => f.ConnectionTypeName == "SomeNameSpace.SomeConnection")
                .FirstOrDefault();
            Assert.IsNotNull(factory);

            DbMetadataProviderFactories.RegisterMetadataProviderFactory(new DummyMetadataProviderFactory());
        }




        protected abstract IDbConnection CreateConnection();


        protected abstract DbMetadataExtractor CreateMetadataExtractor(IDbConnection dbConnection);

    }
}
